<!DOCTYPE html>
<meta charset="utf-8">

<title>Hoopla</title>
<link rel="stylesheet" type="text/css" href="style.css">
<!-- 引入Three.js库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<!-- 引入星空粒子背景特效 -->
<script type="text/javascript" src="starfield-bg.js"></script>

<script type="text/javascript" src="lib/underscore.js"></script>
<script type="text/javascript" src="lib/eelens.js"></script>
<script type="text/javascript" src="lib/canvas.js"></script>
<script type="text/javascript" src="lib/conrec.js"></script>
<script type="text/javascript" src="lib/optimize.js"></script>
<script type="text/javascript" src="hoopla.js"></script>
<script src="https://cdn.jsdelivr.net/pyodide/v0.28.1/full/pyodide.js"></script>
<script type="text/javascript" src="lib/hdf5.js"></script>
<script type="text/javascript" src="lib/fits.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pako@2.1.0/dist/pako.min.js"></script>
<!-- 导入分离的模块 -->
<script type="module" src="fileHandler.js"></script>
<script type="module" src="uiHandler.js"></script>

<script type="text/javascript">
	var src = "images/Figure_26.png";
	var img_name = "Figure_26.png";
	var imgd = new Image();
	imgd.crossOrigin="anonymous";
	imgd.src = src;
	imgd.width = 400;
	imgd.height = 400;
	var scale = 1.0;
	var globalImageData = null;
	var lets,ms,ms_src,containerEl,containerEl_src,img,img_src;
	// 在全局作用域声明
	let pyodide = null;
	// 全局变量，用于模块访问
	window.chartInstance = null;
	// 初始化函数
	async function initPyodide() {
		try {
			console.log("开始初始化Pyodide...");
			pyodide = await loadPyodide();
			console.log("Pyodide基础环境加载完成");
			// 分别加载numpy和scipy，并添加错误处理
			try {
				await pyodide.loadPackage('numpy');
				// console.log("numpy加载完成");
				await pyodide.loadPackage('scipy');
				// console.log("scipy加载完成");
				console.log("所有Python包加载完成");
				return true;
			} catch (packageError) {
				throw new Error("Python包加载失败: " + packageError.message);
			}
		} catch (error) {
			console.error("Pyodide初始化失败:", error);
			return false;
		}
	}
	
	// 初始化工作，包括对象的生成及赋值，以及一些函数操作
	function setup(){
		// Create a hoopla object. The ID is that of the <div>
		lets = new Hoopla({
			id:'hoopla-srcmodel',
			srcmodel: 'hoopla-srcmodel',
			prediction: 'hoopla-prediction',
			pixscale: 0.025,
		});
		var bar = document.getElementsByClassName("bar");
		for (let i=0; i<bar.length;i++){
			bar[i].style.backgroundImage = "url(" + src + ")";
		}
		// Using Brian C's Marking Surface library!!!
		ms = new MarkingSurface({
			inputName: 'mass-model',
			tool: MarkingSurface.EllipseTool,
		});

		containerEl = document.getElementById("marking-container");
		containerEl.appendChild(ms.el);

		img = new Image();
		img.onload = function() {
			let width = img.width;
			let height = img.height;

			ms.addShape('image', {
				'xlink:href': img.src,
				width: width,
				height: height
			});
			ms.svg.attr({
				width: width,
				height: height
			});
			ms.rescale(0, 0, width, height);
			let scaleX = width / img.width;
			let scaleY = height / img.height;

			function getThetaE(d) {
				let a = d.rx * lets.pixscale;
				let b = d.ry * lets.pixscale;
				return Math.sqrt(a * b);
			}

			function getAratio(d) {
				let a = d.rx;
				let b = d.ry;
				return a / b;
			}

			function getAngle(d) {
				if (d.angle < 0) {
					return d.angle + 180;
				}
				return d.angle%180;
			}

			function getCoords(d) {
				return lets.lens.pix2ang({x: scaleX * d.x, y: scaleY * d.y});
			}

			function updateModel() {
				let data = JSON.parse(ms.getValue());
				let components = data.map(function(d) {
					let coords = getCoords(d);
					return {
						plane: "lens",
						theta_e: getThetaE(d),
						ell: getAratio(d),
						ang: getAngle(d),
						x: coords.x,
						y: coords.y
					}
				});
				lets.updateModel(components);
			}
			let debouncedUpdateModel = _.debounce(updateModel, 200);
			ms.on('marking-surface:change', debouncedUpdateModel);
		}
		img.src = src;

		// Source Models
		ms_src = new MarkingSurface({
			inputName: 'src-model',
			tool: MarkingSurface.EllipseTool
		});
		containerEl_src = document.getElementById("marking-container-src");
		containerEl_src.appendChild(ms_src.el);

		img_src = new Image();
		img_src.onload = function() {
			let width = img_src.width;
			let height = img_src.height;

			ms_src.addShape('image', {
				'xlink:href': img_src.src,
				width: width,
				height: height
			});
			ms_src.svg.attr({
				width: width,
				height: height
			});
			ms_src.rescale(0, 0, width, height);
			let scaleX = width / img_src.width;
			let scaleY = height / img_src.height;

			function getSize(d) {
				let a = d.rx * lets.pixscale;
				let b = d.ry * lets.pixscale;
				return Math.sqrt(a * b);
			}

			function getAratio(d) {
				let a = d.rx;
				let b = d.ry;
				return a / b;
			}

			function getAngle(d) {
				if (d.angle < 0) {
					return d.angle + 180;
				}
				return d.angle%180;
			}

			function getCoords(d) {
				return lets.lens.pix2ang({x: scaleX * d.x, y: scaleY * d.y});
			}

			function updateModel() {
				let data = JSON.parse(ms_src.getValue());
				let components = data.map(function(d) {
					let coords = getCoords(d);
					return {
						plane: "source",
						size: getSize(d),
						ell: getAratio(d),
						ang: getAngle(d),
						x: coords.x,
						y: coords.y,
						n_sersic: 1.0,
						Ie: 1.0,
					}
				});
				lets.updateModel(components);
			}

			let debouncedUpdateModel = _.debounce(updateModel, 200);
			ms_src.on('marking-surface:change', debouncedUpdateModel);
		}
		img_src.src = src;
		console.log(src);
	}

	window.onload = async function (e) {
		try {
			await initPyodide();  // 先将pyoide启动
		}catch (e) {
			console.log("pyoide启动失败,错误:",e);
		}
		setup();
		document.getElementById('imageUpload').onclick = function (e) {
			if (window.cleanupCanvas) {
				window.cleanupCanvas();
			}
			document.getElementById("imgURL").innerText = "";
			document.getElementById("pixel-scale").value = "";
			document.querySelector('.popup-form').classList.add('active');
		};
		document.getElementById("close-form-button").onclick = function () {
			document.querySelector('.popup-form').classList.remove('active');
		}

		document.getElementById("image-url").onchange = async function () {
			let imageFile = this.files[0];
			try {
				// 动态导入模块
				const fileModule = await import('./fileHandler.js');
				
				const result = await fileModule.handleImageUpload(imageFile);
				document.getElementById("imgURL").innerText = result.url;
				img_name = result.imgName;
			} catch (error) {
				window.alert(error.message);
			}
		};
		
		img0 = new Image();
		img0.onload = function() {
			// 目标画布大小
			const targetWidth = 400;
			const targetHeight = 400;
			console.log("原始图片宽度:", img0.width, "高度:", img0.height);
			console.log("目标画布宽度:", targetWidth, "高度:", targetHeight);
			// 计算缩放比例
			const scaleX = targetWidth / img0.width;
			const scaleY = targetHeight / img0.height;
			scale = Math.max(scaleX, scaleY); // 取较大的缩放比例以铺满画布
			console.log("缩放比例:", scale);
			// 计算缩放后的图像尺寸
			const scaledWidth = img0.width * scale;
			const scaledHeight = img0.height * scale;
			// 创建临时画布进行图像缩放
			const tempCanvas = document.createElement('canvas');
			tempCanvas.width = targetWidth;
			tempCanvas.height = targetHeight;
			const tempCtx = tempCanvas.getContext('2d');
			// 清除临时画布
			tempCtx.clearRect(0, 0, targetWidth, targetHeight);
			// 在临时画布中央绘制缩放后的图像
			const xOffset = (targetWidth - scaledWidth) / 2;
			const yOffset = (targetHeight - scaledHeight) / 2;
			tempCtx.drawImage(img0, xOffset, yOffset, scaledWidth, scaledHeight);
			// 获取缩放后的图像URL
			const scaledUrl = tempCanvas.toDataURL();
			// 更新所有图像和画布
			lets.width = targetWidth;
			lets.height = targetHeight;
			img.src = scaledUrl;
			img_src.src = scaledUrl;
			imgd.src = scaledUrl; 
			imgd.width = targetWidth; 
			imgd.height = targetHeight;

			lets.srcmodelPaper.clear();
			lets.srcmodelPaper.src = scaledUrl;
			lets.srcmodelPaper.width = targetWidth;
			lets.srcmodelPaper.height = targetHeight;

			lets.predictionPaper.clear();
			lets.predictionPaper.src = scaledUrl;
			lets.predictionPaper.width = targetWidth;
			lets.predictionPaper.height = targetHeight;

			lets.paper.src = scaledUrl;
			lets.paper.width = targetWidth;
			lets.paper.height = targetHeight;

			lets.resetLens(targetWidth, targetHeight, lets.pixscale);

			// 更新所有bar元素
			let bar = document.getElementsByClassName("bar");
			for (let i = 0; i < bar.length; i++){
				bar[i].style.backgroundImage = "url(" + scaledUrl + ")";
				bar[i].style.height= targetHeight + "px";
				bar[i].style.width = targetWidth + "px";
				// 确保背景图像覆盖整个bar
				bar[i].style.backgroundSize = "cover";
				bar[i].style.backgroundPosition = "center";
			}
			if(typeof drawResiduals === 'function'){
				drawResiduals();
			}
		}

		document.getElementById("confirm").onclick = async function () {
			let imageFile = window._uploadedImageFile;
			let pixscale = document.getElementById("pixel-scale").value;
			
			// 基本验证
			if (!imageFile) {
				window.alert('Please select a valid file!');
				return;
			}
			if (pixscale === '' || !pixscale) {
				window.alert("Please input entire information of image!");
				return;
			}
			try {
				// 动态导入模块
				const fileModule = await import('./fileHandler.js');
				const uiModule = await import('./uiHandler.js');
				// 调用文件处理模块处理图像
				await fileModule.processImageFile(imageFile, pixscale, img0, lets);
				
				// 重置标记表面
				ms.reset();
				ms_src.reset();
				// 更新像素比例显示
				document.getElementById('newPixelScale').value = pixscale;
				// 关闭弹窗
				document.querySelector('.popup-form').classList.remove('active');
				// 清理卡方曲线图
				if (window.chartInstance) {
					uiModule.cleanupCanvas();
				}
				
			} catch (error) {
				window.alert("Error processing image: " + error.message);
			}
		}

		document.getElementById("saveModel").onclick = async function fun() {
			try {
				// 动态导入模块
				const fileModule = await import('./fileHandler.js');
				
				// 调用文件处理模块保存模型
				await fileModule.saveModelToFile(img_src.src, lets);
			} catch (error) {
				window.alert("Error saving model: " + error.message);
			}
		};

		document.getElementById('modelUpload').onchange = async function (e) {
			
			let input = e.target;
			let modelFile = input.files[0];
			
			try {
				// 动态导入模块
				const fileModule = await import('./fileHandler.js');
				
				// 调用文件处理模块加载模型
				await fileModule.loadModelFile(
					modelFile, 
					updateCanvas,
					show_res, 
					lets,
					scale
				);
				// 无论成功或失败，都清空文件输入字段，允许重新上传相同或已更改的文件
				input.value = '';
			} catch (error) {
				window.alert("Error loading model: " + error.message);
				// 清空文件输入字段，允许重新上传相同或已更改的文件
				input.value = '';
			}
		};
	}

	// 重置pixel scale
  function reset() {
    // 清理参数趋势图
    if (window.cleanupCanvas) {
      window.cleanupCanvas();
    }
    
    const pixscaleInput = document.getElementById('newPixelScale');
    const pixscale = pixscaleInput.value;
    
    // 导入uiHandler模块并调用resetPixelScale函数
    import('./uiHandler.js').then(uiModule => {
      uiModule.resetPixelScale(pixscale, window.lets, window.scale);
      pixscaleInput.focus();
    }).catch(error => {
      console.error('Error importing uiHandler module:', error);
      
      // 备用实现
      const regex = /^\d{0,2}(\.\d{0,6})?$/;
      if(regex.test(pixscale)){
        if (window.lets) {
          const scaleValue = window.fileHandlerScale || 1;
          window.lets.pixscale = parseFloat(pixscale)/scaleValue;
          // 同时更新模型中的像素比例
          if (window.lets.model) {
            window.lets.model.pixscale = window.lets.pixscale;
          }
          console.log('Updated pixel scale:', window.lets.pixscale);
          
          // 重置标记表面（如果可用）
          if (window.ms) window.ms.reset();
          if (window.ms_src) window.ms_src.reset();
        }
      }else{
        window.alert('Pixel-scale is not a legitimate input!');
      }
    });
  }
	
	// 仅监听maskRadius输入框的input事件，DOM加载时不执行绘制操作
document.addEventListener('DOMContentLoaded', function() {
	const maskRadiusInput = document.getElementById('maskRadius');
	if (maskRadiusInput) {
		maskRadiusInput.addEventListener('input', function() {
			if (typeof lets !== 'undefined' && typeof lets.drawMaskOutline === 'function') {
				lets.drawMaskOutline();
			}
		});
	}
	
	// 处理模型参数对比线开关
	const modelComparisonToggle = document.getElementById('modelComparisonToggle');
	if (modelComparisonToggle) {
		// 初始化开关状态
		if (typeof window.drawModelComparisonLine !== 'undefined') {
			modelComparisonToggle.checked = window.drawModelComparisonLine;
		}
		
		// 添加点击事件监听器
		modelComparisonToggle.addEventListener('change', function() {
			window.drawModelComparisonLine = this.checked;
			console.log('模型参数对比线功能已' + (this.checked ? '启用' : '禁用'));
		});
	}
	
});

	function applyMask() {
		// 清理参数趋势图
		if (window.cleanupCanvas) {
			window.cleanupCanvas();
		}
		return window.imageProcessor.applyMask();
	}

	async function delForeground() {
		return window.imageProcessor.delForeground();
	}

</script>

<body>
<div>
	<header class="inner">
		<h1>Hoopla</h1>
		<h4><a href="https://gitee.com/long-jianchao/Hoopla-Preprocessing_input_pics">Lens
			Modeling in Javascript</a> with Elliptical Lenses and Sources</h4>
	</header>
</div>

<div style="display: flex; gap: 10px; margin: 10px;">
	<!-- 现有的6个画布表格 -->
	<div style="flex: 1;">
		<table>
	<tr class="container">
		<td>
			<div class="barTitle">
			<p>Mass Model</p>
		</div>
		</td>
		<td>
			<div class="barTitle">
			<p>Source Model</p>
		</div>
		</td>
        <td>
            <div class="barTitle">
                <p>Chi-Square Curve</p>
            </div>
        </td>
	</tr>
	<tr class="container">
		<td>
			<div id="marking-container" class="bar"></div>
		</td>
		<td>
			<div id="marking-container-src" class="bar" style="color: #666666;"></div>
		</td>
        <td>
            <canvas id="Curve"  width="400" height="400" style="background-color: whitesmoke;border:1px solid #d3d3d3;float: left;margin: 5px;"></canvas>
        </td>
	</tr>
	<tr class="container">
		<td>
			<div class="barTitle">
			<p>Source Plane</p>
		</div>
		</td>
		<td>
			<div class="barTitle">
			<p>Image Plane</p>
		</div>
		</td>
        <td>
            <div class="barTitle">
				<p>Residual Map</p>
            </div>
        </td>
	</tr>

	<tr class="container">
		<td>
			<div id="hoopla-srcmodel" class="bar">
				<p id="tag" class="tooltip" style="display: block">
					<span class="tooltiptext">Interactive Mode is activated, click left button of the mouse to turn into Freezed mode.</span>
					Interactive
				</p>
			</div>
		</td>
		<td>
			<div id="hoopla-prediction" class="bar">
				<p id="tag2" style="background-color: #8ee58a;display: none;">Running...</p>
			</div>
		</td>
        <td>
            <canvas id="myCanvas"  width="400" height="400" style="border:1px solid #d3d3d3;float: left;margin: 5px;"></canvas>
        </td>
	</tr>

		</table>
	</div>
	
	<!-- 参数走势图容器 -->
	<div style="flex: 1; min-width: 0;">
		<div class="paramChartTitle">
			<p>Parameter Trending Charts</p>
		</div>
		<div id="paramsTrendContainer" style="flex: 1; min-width: 0;">
		<!-- 参数走势图容器，4*3布局 -->
		<div style="display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(4, auto); gap: 4px; padding: 8px;">
			<!-- 第一行 -->
			<div class="chart-container">
				<canvas id="paramChart_0" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_1" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_2" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<!-- 第二行 -->
			<div class="chart-container">
				<canvas id="paramChart_3" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_4" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_5" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<!-- 第三行 -->
			<div class="chart-container">
				<canvas id="paramChart_6" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_7" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_8" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<!-- 第四行 -->
			<div class="chart-container">
				<canvas id="paramChart_9" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_10" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
			<div class="chart-container">
				<canvas id="paramChart_11" width="320" height="200" style="width: 100%; height: 100%;"></canvas>
			</div>
		</div>
	</div>
	</div>
</div>

<div class="container" style="width: 1300px">
	<button class="button" id="saveModel"
			style="vertical-align:middle;width:193px;"><span>Save Models</span>
	</button>
	<button class="Uploadbtn"  style="vertical-align:middle;width:193px;">
		<input class="input-upload" type="file" id="modelUpload"/>
		<span>Load Models</span>
	</button>

	<button class="Uploadbtn"  style="vertical-align:middle;width:193px;">
		<input class="input-upload" type="button" id="imageUpload"/>
		<span>Upload Images</span>
	</button>
	<button class="button" id="delForeground" onclick="delForeground()"
            style="vertical-align:middle;width:193px;"><span>Extract Lens Arc</span>
    </button>
    <button class="button" id="optimization" onclick="do_fit()"
            style="vertical-align:middle;width:193px"><span>Optimization</span>
    </button>
    <button class="button" id="mcmcButton" onclick="startMCMC()"
            style="vertical-align:middle;width:193px;background-color:#e84d05"><span>MCMC</span>
    </button>

</div>
<div class="container" style="height: 50px; width: 1000px;">
	<span>Current pixel-scale: </span>
	<input class="pixscale" id="newPixelScale" type="number">
	<button class="button" onclick="reset()" style="width: 200px;vertical-align: middle">
		<span>Reset Pixel-Scale</span>
	</button>
	<span style="margin-left: 10px;">Mask Radius:</span>
	<input type="number" id="maskRadius" min="0" step="1" style="width: 80px; margin-left: 5px; border-radius: 5px;">
	<button class="button" onclick="applyMask()" style="width: 150px;vertical-align: middle; margin-left: 10px;">
		<span>Apply Mask</span>
	</button>
</div>
<div class="container" style="height: 40px; width: 1000px;">
	<label style="color: white; margin-right: 10px;">
		<input type="checkbox" id="modelComparisonToggle" checked style="margin-right: 5px;">
		绘制模型参数对比线
	</label>
</div>

<div class="popup-form">
	<h2 style="color: black;text-align: center">Image Settings</h2>
	<form onsubmit="return false;">
		<div class="form-item1">
			<label for="image-url" style="margin-right: 80px;">Image URL:</label>
			<button class="Uploadbtn" id="img-upload"  style="width:200px;background-color:#1fc0db">
				<input class="input-upload" type="file"  id="image-url" />
				<span>Select Image</span>
			</button>
			<br/>
			<span id="imgURL" content="" style="width: 100%;height: 30px;color: black"></span>
		</div>

		<br/>
		<div class="form-item">
			<label for="pixel-scale">Pixel Scale (px):</label>
			<input type="text" id="pixel-scale" placeholder="Enter the pixel size of the image">
		</div>
		<br/>
		<div class="form-item">
			<button type="submit" id="confirm" >Confirm</button>
			<button type="button" id="close-form-button" >Close</button>
		</div>
	</form>
</div>

<!-- MCMC等待特效 -->
<div class="loading-overlay" id="loadingOverlay">
	<div class="loading-content">
		<div class="loading"></div>
		<!-- MCMC进度条 -->
		<div id="timeEstimate" class="progress-time">预计建模时间: 3分钟</div>
		<div class="progress-container">
			<div id="mcmcProgressBar" class="progress-bar">
				<div class="progress-fill"></div>
				<div class="progress-glow"></div>
			</div>
		</div>
		<div id="progressText" class="progress-text">0% 完成 (0:00 / 3:00)</div>
		
		<h3>模型日志</h3>
		<pre id="log" style="color:rgb(255, 255, 255); padding:10px;width: 800px; height:400px; overflow:auto; font-size:14px;"></pre>
	</div>
</div>

<div id="result-container">
  <div class="result-images-container">
    <!-- 根据原始比例设置相同高度 -->
    <div class="result-image-wrapper">
      <img id="result-img" class="result-image">
    </div>
    <div class="result-image-wrapper">
      <img id="corner-img" class="result-image">
    </div>
  </div>

  <div class="result-actions">
    <button id="save-btn">💾 Save Result</button>
    <button id="continue-btn">🔁 Next Modeling</button>
  </div>
</div>

<!-- 图片查看器模态窗口 -->
<div id="image-viewer" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.9); z-index:1000; justify-content:center; align-items:center;">
  <div style="position:relative; display:inline-block;">
    <img id="viewer-img" style="max-width:90%; max-height:90vh; transform-origin:center; cursor:grab;"
         onmousedown="this.style.cursor='grabbing'"
         onmouseup="this.style.cursor='grab'"
         onmouseleave="this.style.cursor='grab'">
    <button onclick="closeImageViewer()" style="position:absolute; top:-40px; right:0; background:none; border:none; color:white; font-size:30px; cursor:pointer;">
      ×
    </button>
    <div style="position:absolute; bottom:-40px; left:50%; transform:translateX(-50%); color:white; font-size:14px;">
      滚轮放大缩小 | 拖拽查看局部 | 点击关闭按钮或背景返回 | Esc键退出
    </div>
  </div>
</div>


</body>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="text/javascript" src="lib/marking/marking-surface.js"></script>
<script type="text/javascript" src="lib/marking/tools/ellipse.js"></script>
<!-- 外部JavaScript模块 -->
<script type="text/javascript" src="mcmcHandler.js"></script>
<script type="text/javascript" src="imageViewer.js"></script>
<script type="text/javascript" src="optimization.js"></script>
<script type="text/javascript" src="imageProcessor.js"></script>

<!-- 在函数定义后设置全局变量引用 -->
<script>
  // 在相关脚本加载后设置全局函数引用
  if (typeof drawChiSquareCurve === 'function') {
    window.drawChiSquareCurve = drawChiSquareCurve;
  }
  if (typeof updateCanvas === 'function') {
    window.updateCanvas = updateCanvas;
  }
  if (typeof show_res === 'function') {
    window.show_res = show_res;
  }
  if (typeof getImage === 'function') {
    window.getImage = getImage;
  }
  
  // 页面加载完成后初始化参数走势图
  document.addEventListener('DOMContentLoaded', function() {
    if (typeof initializeParamsTrendChart === 'function') {
      initializeParamsTrendChart();
    }
  });
</script>
